<script lang="ts">
    import Icon from "../Common/Icons/Icon.svelte";
    import { useClassList } from "../utils/useClassList";
    import { useStyle } from "../utils/useStyle";
    import type { ProgressProps, StrokeProps } from "./Progress";

    const props: ProgressProps = $props();
    const max = $derived(props.max ?? 100);
    const value = $derived.by(() => {
        if (props.value && props.value < 0) {
            return 0;
        }
        if (props.value && props.value >= max) {
            return max;
        }
        return props.value ?? 0;
    });
    const strokeWidth = props.strokeWidth ?? 10;
    const type = props.type ?? "line";
    const radius = $derived(props.radius ?? 60);
    const status = $derived.by(() => {
        if (value === 100) {
            return "finished";
        }
        return props.status ?? "normal";
    });
    const classList = $derived(
        useClassList(props, "cm-progress", {
            "cm-progress-hide-info": props.hidePercent,
            [`cm-progress-${status}`]: !!status,
            [`cm-progress-${type}`]: !!type,
        }),
    );

    const width = $derived(`${value}%`);
    const style = $derived.by(() => {
        const obj: any = {
            width: width,
            height: `${strokeWidth}px`,
        };
        if (props.strokeColor) {
            if (typeof props.strokeColor === "string") {
                obj["background-color"] = props.strokeColor;
            }
            if (props.strokeColor instanceof Array) {
                const length = props.strokeColor.length;
                const arr = (props.strokeColor as string[]).map((color: string, index: number) => {
                    return color + " " + (index / length) * 100 + "%";
                });
                obj["background-image"] = `linear-gradient(to right, ${arr.join(",")})`;
            }
        }
        return useStyle({}, obj);
    });

    // 计算当前角度对应的弧度值
    const rad = 2 * Math.PI;

    // 极坐标转换成直角坐标
    const x = $derived((Math.sin(rad) * radius).toFixed(2));
    const y = $derived(-(Math.cos(rad) * radius).toFixed(2));
    const tx = $derived(radius + strokeWidth / 2);

    const descriptions = $derived(["M", 0, -radius, "A", radius, radius, 0, 1, 1, x, -y, "A", radius, radius, 0, 1, 1, x, y]);

    const circleStyle = $derived.by(() => {
        const percent = () => value / max;
        const dd = () => rad * radius;
        const offset = () => dd() * (1 - percent());

        const obj: any = {
            "stroke-dashoffset": `${offset()}`,
            "stroke-dasharray": dd(),
        };
        if (props.strokeColor) {
            if (typeof props.strokeColor === "string") {
                obj["stroke"] = props.strokeColor;
            }
            if (props.strokeColor instanceof Array) {
                for (let i = 0; i < props.strokeColor.length; i++) {
                    const stroke = props.strokeColor[i] as StrokeProps;

                    if (percent() * 100 >= stroke.percent) {
                        obj["stroke"] = stroke.color;
                    }
                }
            }
        }
        return useStyle({}, obj);
    });
</script>

<div class={classList}>
    <div class="cm-progress-outer">
        <div class="cm-progress-inner">
            {#if type === "line"}
                <div class="cm-progress-bar" {style}>
                    {#if props.textInside}
                        <span class="cm-progress-info">{`${value}%`}</span>
                    {/if}
                </div>
            {/if}
            {#if type === "circle"}
                <svg
                    width="100%"
                    height="100%"
                    version="1.1"
                    xmlns="http://www.w3.org/2000/svg"
                    style={`display: block; width: ${2 * radius + strokeWidth + "px"}; height: ${2 * radius + strokeWidth + "px"}`}
                >
                    <circle cx={tx} cy={tx} r={radius} stroke="#f3f3f3" stroke-width={strokeWidth} fill-opacity="0" />
                    <path
                        class="cm-progress-bar-path"
                        d={descriptions.join(" ")}
                        stroke-linecap="round"
                        stroke-width={strokeWidth}
                        fill-opacity="0"
                        transform={`translate(${tx},${tx})`}
                        style={circleStyle}
                    />
                </svg>
            {/if}
        </div>
    </div>
    {#if !props.textInside}
        <span class="cm-progress-info">
            {#if props.infoRender}
                {@render props.infoRender(status, value)}
            {:else if status === "finished"}
                <Icon icon="checkCircle" size={type === "line" ? 12 : 24} />
            {:else if status === "error"}
                <Icon icon="xCircle" size={type === "line" ? 12 : 24} />
            {:else}
                {`${value}%`}
            {/if}
        </span>
    {/if}
</div>
